﻿using System;

namespace ch07.binary
{
    public static class LittleEndian
    {
        public static ushort Uint16(ref byte[] b)
        {
            _ = b[1]; // bounds check hint to compiler; see golang.org/issue/14808
            return (ushort) (b[0] | (ushort) (b[1] << 8));
        }

        public static uint Uint32(ref byte[] b)
        {
            _ = b[3]; // bounds check hint to compiler; see golang.org/issue/14808
            return b[0] | (uint) b[1] << 8 | (uint) b[2] << 16 | (uint) b[3] << 24;
        }

        public static ulong Uint64(ref byte[] b)
        {
            _ = b[7]; // bounds check hint to compiler; see golang.org/issue/14808
            return b[0] | (ulong) b[1] << 8 | (ulong) b[2] << 16 | (ulong) b[3] << 24 |
                   (ulong) b[4] << 32 | (ulong) b[5] << 40 | (ulong) b[6] << 48 | (ulong) b[7] << 56;
        }

        public static void PutUint32(ref byte[] b, uint v)
        {
            _ = b[3]; // early bounds check to guarantee safety of writes below
            b[0] = (byte) (v);
            b[1] = (byte) (v >> 8);
            b[2] = (byte) (v >> 16);
            b[3] = (byte) (v >> 24);
        }


        public static void PutUint64(ref byte[] b, ulong v)
        {
            _ = b[7]; // early bounds check to guarantee safety of writes below
            b[0] = (byte) v;
            b[1] = (byte) (v >> 8);
            b[2] = (byte) (v >> 16);
            b[3] = (byte) (v >> 24);
            b[4] = (byte) (v >> 32);
            b[5] = (byte) (v >> 40);
            b[6] = (byte) (v >> 48);
            b[7] = (byte) (v >> 56);
        }

        public static void PutUint16(ref byte[] b, UInt16 v)
        {
            _ = b[1]; // early bounds check to guarantee safety of writes below
            b[0] = (byte) (v);
            b[1] = (byte) (v >> 8);
        }
    }
}